package jee.boot.common.remote;

import com.google.common.collect.Lists;
import jee.boot.common.CommonConstant;
import jee.boot.common.basic.ServiceException;
import jee.boot.common.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * 跨服务进行远程访问,应用于微服务部署方式,非默认
 */

public class CrossServiceRequest implements RemoteEndpoint {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private RestTemplate restTemplate;

    private ProcessInternalRequest processInternalRequest;


    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public void setProcessInternalRequest(ProcessInternalRequest processInternalRequest) {
        this.processInternalRequest = processInternalRequest;
    }

    /**
     * @param serviceId    远程服务id,
     * @param path         远程服务path
     * @param param        请求参数
     * @param responseType 返回数据类型设定
     * @return 返回响应数据
     */
    @Override
    public <T> T executePost(String serviceId, String path, Object param, Class<?> responseType, boolean processPriority) {
        if (processPriority) {
            // 如果是本地请求实例,则走本地请求
            if (processInternalRequest != null && processInternalRequest.isProcessInternalRequest(path)) {
                return processInternalRequest.executePost(serviceId, path, param, responseType);
            }
        }
        responseType = responseType == null ? (Class<?>) String.class : responseType;
        path = "http://" + serviceId + path;

        HttpHeaders headers = new HttpHeaders();
        // 内部请求忽略刷新token操作
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("IgnoreRefresh", CommonConstant.DATA_STATUS_ACTIVE);
        HttpServletRequest httpServletRequest = HttpServletHolder.getHttpServletRequest();
        if(httpServletRequest!=null){
            Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
            if(headerNames!=null){
                while (headerNames.hasMoreElements()){
                    String element = headerNames.nextElement();
                    if(StringUtils.equalsIgnoreCase(element,"Content-type")){
                        continue;
                    }
                    headers.add(element,httpServletRequest.getHeader(element));
                }
            }
        }
        HttpEntity<String> formEntity = new HttpEntity<String>(JsonMapper.toJsonString(param), headers);
        Map response = restTemplate.postForEntity(path, formEntity, Map.class).getBody();
        if (response != null) {
            // 没有code的时候,直接抛出异常信息
            if (!response.containsKey("code")) {
                logger.error(JsonMapper.toJsonString(response));
                throw new ServiceException();
            }
            // code为非200时候属于业务异常,也要抛出异常
            if (200 != (int) response.get("code")) {
                String message = response.containsKey("message") ? response.get("message").toString() : JsonMapper.toJsonString(response);
                logger.error(message);
                throw new ServiceException((int) response.get("code"));
            }
            // 正常的时候
            if (response.containsKey("data")) {
                Object data = response.get("data");
                if (data instanceof List) {
                    List retList = Lists.newArrayList();
                    List dataList = (List) data;
                    if (!dataList.isEmpty()) {
                        Class<?> finalResponseType = responseType;
                        dataList.forEach(d -> {
                            retList.add(MapUtils.toBean(d, finalResponseType)/*JsonMapper.fromJsonString(JsonMapper.toJsonString(d), finalResponseType)*/);
                        });
                    }
                    return (T) retList;
                } else {
                    T object = (T) MapUtils.toBean(data, responseType);
//                    T object = (T)JsonMapper.fromJsonString(JsonMapper.toJsonString(data), responseType);
                    return object;
                }

            } else {
                try {
                    return responseType == null ? null : (T) responseType.newInstance();
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                    throw new ServiceException();
                }
            }
        } else {
            try {
                return responseType == null ? null : (T) responseType.newInstance();
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new ServiceException();
            }
        }
    }

    /**
     * @param serviceId    远程服务id,
     * @param path         远程服务path
     * @param param        请求参数
     * @param responseType 返回数据类型设定
     * @return 返回响应数据
     */
    @Override
    public <T> T executePost(String serviceId, String path, Object param, Class<?> responseType) {
        boolean processPriority=false;
        if(StringUtils.equals(serviceId, SpringEnvironmentHolder.getValue("spring.application.name"))){
            processPriority=true;
        }
        return this.executePost(serviceId, path, param, responseType, processPriority);
    }

    public static void main(String[] args) {

    }
}
